﻿#include "StdAfx.h"
#include "UILabel.h"

#include <atlconv.h>
namespace DuiLib {
    IMPLEMENT_DUICONTROL(CLabelUI)

    CLabelUI::CLabelUI() :
        m_uTextStyle(DT_VCENTER | DT_SINGLELINE), m_dwTextColor(0),
        m_dwDisabledTextColor(0),
        m_iFont(-1),
        m_bShowHtml(false),
        m_bAutoCalcWidth(false),
        m_bAutoCalcHeight(false),
        m_bNeedEstimateSize(false) {
        m_cxyFixedLast.cx = m_cxyFixedLast.cy = 0;
        m_szAvailableLast.cx = m_szAvailableLast.cy = 0;
        ::ZeroMemory(&m_rcTextPadding, sizeof(m_rcTextPadding));
    }

    CLabelUI::~CLabelUI() {
    }

    LPCTSTR CLabelUI::GetClass() const {
        return DUI_CTR_LABEL;
    }

    LPVOID CLabelUI::GetInterface(LPCTSTR pstrName) {
        if( _tcsicmp(pstrName, DUI_CTR_LABEL) == 0)
            return static_cast<CLabelUI *>(this);

        return CControlUI::GetInterface(pstrName);
    }

    UINT CLabelUI::GetControlFlags() const {
        return IsEnabled() ? UIFLAG_SETCURSOR : 0;
    }

    void CLabelUI::SetTextStyle(UINT uStyle) {
        m_uTextStyle = uStyle;
        Invalidate();
    }

    UINT CLabelUI::GetTextStyle() const {
        return m_uTextStyle;
    }

    void CLabelUI::SetTextColor(DWORD dwTextColor) {
        m_dwTextColor = dwTextColor;
        Invalidate();
    }

    DWORD CLabelUI::GetTextColor() const {
        return m_dwTextColor;
    }

    void CLabelUI::SetDisabledTextColor(DWORD dwTextColor) {
        m_dwDisabledTextColor = dwTextColor;
        Invalidate();
    }

    DWORD CLabelUI::GetDisabledTextColor() const {
        return m_dwDisabledTextColor;
    }

    void CLabelUI::SetFont(int index) {
        m_iFont = index;
        m_bNeedEstimateSize = true;
        Invalidate();
    }

    int CLabelUI::GetFont() const {
        return m_iFont;
    }

    RECT CLabelUI::GetTextPadding() const {
        return m_rcTextPadding;
    }

    void CLabelUI::SetTextPadding(RECT rc) {
        m_rcTextPadding = rc;
        m_bNeedEstimateSize = true;
        Invalidate();
    }

    bool CLabelUI::IsShowHtml() {
        return m_bShowHtml;
    }

    void CLabelUI::SetShowHtml(bool bShowHtml) {
        if( m_bShowHtml == bShowHtml ) return;

        m_bShowHtml = bShowHtml;
        m_bNeedEstimateSize = true;
        Invalidate();
    }

    SIZE CLabelUI::EstimateSize(SIZE szAvailable) {
        if (m_cxyFixed.cx > 0 && m_cxyFixed.cy > 0) {
            // Jeffery: 修复了DPI不为100时, CLabelUI(含派生于它的CButtonUI控件)的size不正确的问题
            //
            return m_pManager->GetDPIObj()->Scale(m_cxyFixed);
        }

        if ((szAvailable.cx != m_szAvailableLast.cx || szAvailable.cy != m_szAvailableLast.cy)) {
            m_bNeedEstimateSize = true;
        }

        if (m_bNeedEstimateSize) {
            CDuiString sText = GetText();
            m_bNeedEstimateSize = false;
            m_szAvailableLast = szAvailable;
            m_cxyFixedLast = m_cxyFixed;

            if ((m_uTextStyle & DT_SINGLELINE) != 0) {
                if (m_cxyFixedLast.cy == 0) {
                    m_cxyFixedLast.cy = m_pManager->GetFontInfo(m_iFont)->tm.tmHeight + 8;
                    m_cxyFixedLast.cy += m_pManager->GetDPIObj()->Scale(m_rcTextPadding.top + m_rcTextPadding.bottom);
                }
                else {
                    m_cxyFixedLast.cy = m_pManager->GetDPIObj()->Scale(m_cxyFixedLast.cy);
                    if (m_cxyFixedLast.cy > szAvailable.cy)
                        m_cxyFixedLast.cy = szAvailable.cy;
                }

                if (m_cxyFixedLast.cx == 0) {
                    if(m_bAutoCalcWidth) {
                        RECT rcText = { 0, 0, 9999, m_cxyFixedLast.cy };

                        if( m_bShowHtml ) {
                            int nLinks = 0;
                            CRenderEngine::DrawHtmlText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, 0, NULL, NULL, nLinks, m_iFont, DT_CALCRECT | m_uTextStyle & ~DT_RIGHT & ~DT_CENTER);
                        } else {
                            CRenderEngine::DrawText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, 0, m_iFont, DT_CALCRECT | m_uTextStyle & ~DT_RIGHT & ~DT_CENTER);
                        }

                        m_cxyFixedLast.cx = rcText.right - rcText.left + m_pManager->GetDPIObj()->Scale(m_rcTextPadding.left + m_rcTextPadding.right);
                    } else {
                        m_cxyFixedLast.cx = szAvailable.cx;
                    }
                }
                else {
                    m_cxyFixedLast.cx = m_pManager->GetDPIObj()->Scale(m_cxyFixedLast.cx);
                    if (m_cxyFixedLast.cx > szAvailable.cx)
                        m_cxyFixedLast.cx = szAvailable.cx;
                }
            } else {
                if( m_cxyFixedLast.cx == 0 ) {
                    m_cxyFixedLast.cx = szAvailable.cx;
                }
                else {
                    m_cxyFixedLast.cx = m_pManager->GetDPIObj()->Scale(m_cxyFixedLast.cx);
                    if (m_cxyFixedLast.cx > szAvailable.cx)
                        m_cxyFixedLast.cx = szAvailable.cx;
                }

                if(m_cxyFixedLast.cy == 0) {
                    if(m_bAutoCalcHeight) {
                        RECT rcText = { 0, 0, m_cxyFixedLast.cx, 9999 };
                        rcText.left += m_rcTextPadding.left;
                        rcText.right -= m_rcTextPadding.right;

                        if( m_bShowHtml ) {
                            int nLinks = 0;
                            CRenderEngine::DrawHtmlText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, 0, NULL, NULL, nLinks, m_iFont, DT_CALCRECT | m_uTextStyle & ~DT_RIGHT & ~DT_CENTER);
                        } else {
                            CRenderEngine::DrawText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, 0, m_iFont, DT_CALCRECT | m_uTextStyle & ~DT_RIGHT & ~DT_CENTER);
                        }

                        m_cxyFixedLast.cy = rcText.bottom - rcText.top + m_pManager->GetDPIObj()->Scale(m_rcTextPadding.top + m_rcTextPadding.bottom);
                    } else {
                        m_cxyFixedLast.cy = szAvailable.cy;
                    }
                }
                else {
                    m_cxyFixedLast.cy = m_pManager->GetDPIObj()->Scale(m_cxyFixedLast.cy);

                    if (m_cxyFixedLast.cy > szAvailable.cy)
                        m_cxyFixedLast.cy = szAvailable.cy;
                }
            }
        }

        return m_cxyFixedLast;
    }

    void CLabelUI::DoEvent(TEventUI &event) {
        if( event.Type == UIEVENT_SETFOCUS ) {
            m_bFocused = true;
            return;
        }

        if( event.Type == UIEVENT_KILLFOCUS ) {
            m_bFocused = false;
            return;
        }

        CControlUI::DoEvent(event);
    }

    void CLabelUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) {
        if( _tcsicmp(pstrName, _T("align")) == 0 ) {
            if( _tcsstr(pstrValue, _T("left")) != NULL ) {
                m_uTextStyle &= ~(DT_CENTER | DT_RIGHT);
                m_uTextStyle |= DT_LEFT;
            }

            if( _tcsstr(pstrValue, _T("center")) != NULL ) {
                m_uTextStyle &= ~(DT_LEFT | DT_RIGHT );
                m_uTextStyle |= DT_CENTER;
            }

            if( _tcsstr(pstrValue, _T("right")) != NULL ) {
                m_uTextStyle &= ~(DT_LEFT | DT_CENTER);
                m_uTextStyle |= DT_RIGHT;
            }
        }
		else if( _tcsicmp(pstrName, _T("valign")) == 0 ) {
            if( _tcsstr(pstrValue, _T("top")) != NULL ) {
                m_uTextStyle &= ~(DT_BOTTOM | DT_VCENTER | DT_WORDBREAK);
                m_uTextStyle |= (DT_TOP | DT_SINGLELINE);
            }

            if( _tcsstr(pstrValue, _T("vcenter")) != NULL ) {
                m_uTextStyle &= ~(DT_TOP | DT_BOTTOM | DT_WORDBREAK);
                m_uTextStyle |= (DT_VCENTER | DT_SINGLELINE);
            }

            if( _tcsstr(pstrValue, _T("bottom")) != NULL ) {
                m_uTextStyle &= ~(DT_TOP | DT_VCENTER | DT_WORDBREAK);
                m_uTextStyle |= (DT_BOTTOM | DT_SINGLELINE);
            }
        } 
		else if( _tcsicmp(pstrName, _T("endellipsis")) == 0 ) {
            if( _tcsicmp(pstrValue, _T("true")) == 0 ) 
                m_uTextStyle |= DT_END_ELLIPSIS;
            else 
                m_uTextStyle &= ~DT_END_ELLIPSIS;
        }
		else if( _tcsicmp(pstrName, _T("wordbreak")) == 0 ) {
            if( _tcsicmp(pstrValue, _T("true")) == 0 ) {
                m_uTextStyle &= ~DT_SINGLELINE;
                m_uTextStyle |= DT_WORDBREAK | DT_EDITCONTROL;
            } else {
                m_uTextStyle &= ~DT_WORDBREAK & ~DT_EDITCONTROL;
                m_uTextStyle |= DT_SINGLELINE;
            }
        }
		else if( _tcsicmp(pstrName, _T("noprefix")) == 0 ) {
            if( _tcsicmp(pstrValue, _T("true")) == 0) {
                m_uTextStyle |= DT_NOPREFIX;
            } else {
                m_uTextStyle = m_uTextStyle & ~DT_NOPREFIX;
            }
        }
        else if (_tcsicmp(pstrName, _T("font")) == 0) {
            SetFont(_ttoi(pstrValue));
        }
        else if( _tcsicmp(pstrName, _T("textcolor")) == 0 ) {
            if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);

            LPTSTR pstr = NULL;
            DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
            SetTextColor(clrColor);
        } 
        else if( _tcsicmp(pstrName, _T("disabledtextcolor")) == 0 ) {
            if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);

            LPTSTR pstr = NULL;
            DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
            SetDisabledTextColor(clrColor);
        } 
        else if( _tcsicmp(pstrName, _T("textpadding")) == 0 ) {
            RECT rcTextPadding = { 0 };
            LPTSTR pstr = NULL;
            rcTextPadding.left = _tcstol(pstrValue, &pstr, 10);
            ASSERT(pstr);
            rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10);
            ASSERT(pstr);
            rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10);
            ASSERT(pstr);
            rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10);
            ASSERT(pstr);
            SetTextPadding(rcTextPadding);
        } 
        else if( _tcsicmp(pstrName, _T("showhtml")) == 0 ) 
            SetShowHtml(_tcsicmp(pstrValue, _T("true")) == 0);
        else if( _tcsicmp(pstrName, _T("autocalcwidth")) == 0 ) {
            SetAutoCalcWidth(_tcsicmp(pstrValue, _T("true")) == 0);
        } 
        else if( _tcsicmp(pstrName, _T("autocalcheight")) == 0 ) {
            SetAutoCalcHeight(_tcsicmp(pstrValue, _T("true")) == 0);
        } 
        else
            CControlUI::SetAttribute(pstrName, pstrValue);
    }

    void CLabelUI::PaintText(HDC hDC) {
        if( m_dwTextColor == 0 ) 
            m_dwTextColor = m_pManager->GetDefaultFontColor();

        if( m_dwDisabledTextColor == 0 ) 
            m_dwDisabledTextColor = m_pManager->GetDefaultDisabledColor();

        RECT rc = m_rcItem;
        RECT rcTextPadding = m_rcTextPadding;
        m_pManager->GetDPIObj()->Scale(&rcTextPadding);
        rc.left += rcTextPadding.left;
        rc.right -= rcTextPadding.right;
        rc.top += rcTextPadding.top;
        rc.bottom -= rcTextPadding.bottom;

        CDuiString sText = GetText();

        if( sText.IsEmpty() ) 
            return;

        int nLinks = 0;

        if( IsEnabled() ) {
            if( m_bShowHtml )
                CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, sText, m_dwTextColor, NULL, NULL, nLinks, m_iFont, m_uTextStyle);
            else
                CRenderEngine::DrawText(hDC, m_pManager, rc, sText, m_dwTextColor, m_iFont, m_uTextStyle);
        } else {
            if( m_bShowHtml )
                CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, sText, m_dwDisabledTextColor, NULL, NULL, nLinks, m_iFont, m_uTextStyle);
            else
                CRenderEngine::DrawText(hDC, m_pManager, rc, sText, m_dwDisabledTextColor, m_iFont, m_uTextStyle);
        }
    }

    bool CLabelUI::GetAutoCalcWidth() const {
        return m_bAutoCalcWidth;
    }

    void CLabelUI::SetAutoCalcWidth(bool bAutoCalcWidth) {
        m_bAutoCalcWidth = bAutoCalcWidth;
    }

    bool CLabelUI::GetAutoCalcHeight() const {
        return m_bAutoCalcHeight;
    }

    void CLabelUI::SetAutoCalcHeight(bool bAutoCalcHeight) {
        m_bAutoCalcHeight = bAutoCalcHeight;
    }

    void CLabelUI::SetText( LPCTSTR pstrText ) {
        CControlUI::SetText(pstrText);

        if(GetAutoCalcWidth() || GetAutoCalcHeight()) {
            NeedParentUpdate();
        }
    }
}